"""
文件名: user.py
描述: 用户数据模型定义

本模块包含以下主要功能：
1. User数据库模型 - SQLAlchemy ORM模型
2. UserCreate - 用户创建时的数据验证模型
3. UserUpdate - 用户更新时的数据验证模型
4. UserInDB - 数据库查询返回的用户模型
5. 用户相关的辅助方法和属性

依赖模块:
   - sqlalchemy: ORM框架和数据库操作
   - pydantic: 数据验证和序列化
   - datetime: 时间处理
   - typing: 类型注解

使用示例:
   >>> from src.models.user import User, UserCreate
   >>> user_data = UserCreate(
   ...     email="test@example.com",
   ...     name="Test User",
   ...     google_id="123456789"
   ... )
   >>> user = User(**user_data.dict())

注意事项:
   - 用户的敏感信息（如tokens）需要加密存储
   - OAuth tokens有过期时间，需要定期刷新
   - 用户删除采用软删除方式
   - 遵循GDPR等数据保护法规

作者: AI助手
创建日期: 2024-06-27
最后修改: 2024-06-27
版本: 1.0.0
"""

from datetime import datetime
from typing import Optional

from sqlalchemy import Column, String, DateTime, Boolean, Text, Integer
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.sql import func
import uuid

from pydantic import BaseModel, EmailStr, Field, validator

from src.core.database import Base


class User(Base):
    """
    用户数据库模型
    
    存储用户基本信息和OAuth认证相关数据
    """
    __tablename__ = "users"
    
    # 主键和基本信息
    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True)
    email = Column(String(255), unique=True, index=True, nullable=False, comment="用户邮箱")
    name = Column(String(100), nullable=False, comment="用户姓名")
    avatar = Column(Text, nullable=True, comment="头像URL")
    
    # Google OAuth相关信息
    google_id = Column(String(100), unique=True, index=True, nullable=False, comment="Google用户ID")
    access_token = Column(Text, nullable=True, comment="访问令牌（加密存储）")
    refresh_token = Column(Text, nullable=True, comment="刷新令牌（加密存储）")
    token_expires_at = Column(DateTime(timezone=True), nullable=True, comment="令牌过期时间")
    
    # 用户状态
    is_active = Column(Boolean, default=True, nullable=False, comment="用户是否激活")
    is_premium = Column(Boolean, default=False, nullable=False, comment="是否为高级用户")
    last_login_at = Column(DateTime(timezone=True), nullable=True, comment="最后登录时间")
    last_sync_at = Column(DateTime(timezone=True), nullable=True, comment="最后同步时间")
    
    # 统计信息
    total_channels = Column(Integer, default=0, nullable=False, comment="订阅频道总数")
    total_categories = Column(Integer, default=0, nullable=False, comment="创建分类总数")
    
    # 时间戳
    created_at = Column(
        DateTime(timezone=True), 
        server_default=func.now(), 
        nullable=False,
        comment="创建时间"
    )
    updated_at = Column(
        DateTime(timezone=True), 
        server_default=func.now(), 
        onupdate=func.now(),
        nullable=False,
        comment="更新时间"
    )
    deleted_at = Column(DateTime(timezone=True), nullable=True, comment="删除时间（软删除）")
    
    def __repr__(self) -> str:
        return f"<User(id={self.id}, email={self.email}, name={self.name})>"
    
    @property
    def is_token_expired(self) -> bool:
        """检查访问令牌是否过期"""
        if not self.token_expires_at:
            return True
        return datetime.utcnow() >= self.token_expires_at
    
    @property
    def is_deleted(self) -> bool:
        """检查用户是否被删除"""
        return self.deleted_at is not None


class UserBase(BaseModel):
    """用户基础数据模型"""
    email: EmailStr = Field(..., description="用户邮箱地址")
    name: str = Field(..., min_length=1, max_length=100, description="用户姓名")
    avatar: Optional[str] = Field(None, description="头像URL")
    
    class Config:
        from_attributes = True


class UserCreate(UserBase):
    """用户创建数据模型"""
    google_id: str = Field(..., min_length=1, max_length=100, description="Google用户ID")
    access_token: Optional[str] = Field(None, description="访问令牌")
    refresh_token: Optional[str] = Field(None, description="刷新令牌")
    token_expires_at: Optional[datetime] = Field(None, description="令牌过期时间")
    
    @validator("email")
    def validate_email(cls, v):
        """验证邮箱格式"""
        if not v or "@" not in v:
            raise ValueError("邮箱格式无效")
        return v.lower()
    
    @validator("name")
    def validate_name(cls, v):
        """验证用户名"""
        if not v or not v.strip():
            raise ValueError("用户名不能为空")
        return v.strip()


class UserUpdate(BaseModel):
    """用户更新数据模型"""
    name: Optional[str] = Field(None, min_length=1, max_length=100, description="用户姓名")
    avatar: Optional[str] = Field(None, description="头像URL")
    is_active: Optional[bool] = Field(None, description="用户状态")
    is_premium: Optional[bool] = Field(None, description="高级用户状态")
    access_token: Optional[str] = Field(None, description="访问令牌")
    refresh_token: Optional[str] = Field(None, description="刷新令牌")
    token_expires_at: Optional[datetime] = Field(None, description="令牌过期时间")
    last_login_at: Optional[datetime] = Field(None, description="最后登录时间")
    last_sync_at: Optional[datetime] = Field(None, description="最后同步时间")
    
    @validator("name")
    def validate_name(cls, v):
        """验证用户名"""
        if v is not None and (not v or not v.strip()):
            raise ValueError("用户名不能为空")
        return v.strip() if v else v
    
    class Config:
        from_attributes = True


class UserInDB(UserBase):
    """数据库查询返回的用户模型"""
    id: uuid.UUID = Field(..., description="用户ID")
    google_id: str = Field(..., description="Google用户ID")
    is_active: bool = Field(..., description="用户状态")
    is_premium: bool = Field(..., description="高级用户状态")
    last_login_at: Optional[datetime] = Field(None, description="最后登录时间")
    last_sync_at: Optional[datetime] = Field(None, description="最后同步时间")
    total_channels: int = Field(..., description="订阅频道总数")
    total_categories: int = Field(..., description="创建分类总数")
    created_at: datetime = Field(..., description="创建时间")
    updated_at: datetime = Field(..., description="更新时间")
    
    # 敏感信息不包含在返回模型中
    # access_token, refresh_token, token_expires_at 等不在此模型中
    
    @property
    def display_name(self) -> str:
        """获取显示名称"""
        return self.name or self.email.split("@")[0]
    
    @property
    def is_new_user(self) -> bool:
        """判断是否为新用户（注册7天内）"""
        if not self.created_at:
            return False
        return (datetime.utcnow() - self.created_at).days <= 7


class UserStats(BaseModel):
    """用户统计信息模型"""
    total_channels: int = Field(..., description="订阅频道总数")
    total_categories: int = Field(..., description="创建分类总数")
    total_videos_cached: int = Field(..., description="缓存视频总数") 
    last_sync_at: Optional[datetime] = Field(None, description="最后同步时间")
    sync_status: str = Field(..., description="同步状态")
    
    class Config:
        from_attributes = True


class UserProfile(BaseModel):
    """用户个人资料模型（公开信息）"""
    id: uuid.UUID = Field(..., description="用户ID")
    name: str = Field(..., description="用户姓名")
    avatar: Optional[str] = Field(None, description="头像URL")
    is_premium: bool = Field(..., description="高级用户状态")
    total_channels: int = Field(..., description="订阅频道总数")
    total_categories: int = Field(..., description="创建分类总数")
    created_at: datetime = Field(..., description="注册时间")
    
    class Config:
        from_attributes = True